# coding=utf-8
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import viewsets
from django.db.models import Q
from rest_framework.decorators import action

from basic_info.models import SettlementAccountModel
from basic_info.serializer.settlement_account_serilalizer import AccountSerializer
from MSB_ERP.utils.pagination import GlobalPagination
from MSB_ERP.utils.base_views import MultipleOpenMixin, MultipleDestoryMixin
class AccountView(viewsets.ModelViewSet, MultipleDestoryMixin, MultipleOpenMixin):
    """
    create:
    结算账户信息--新增

    结算账户信息新增, status: 201(成功), return: 新增结算账户信息信息

    destroy:
    结算账户信息--删除

    结算账户信息删除, status: 204(成功), return: None

    multiple_delete:
    结算账户信息--批量删除,必传json参数：ids=[1,2,3,4...]

    结算账户信息批量删除, status: 204(成功), return: None

    multiple_open:
    结算账户信息--批量启用或者禁用,必传(json)参数：ids=[1,2,3,4...](列表中可以只有一个)，is_open=1/0

    {
        "ids":[1,2],
        "is_open":"0"
    }
    is_open=1表示禁用，is_open=0表示启用，
    结算账户信息批量启用或者禁用, status: 204(成功), return: None

    update:
    结算账户信息--修改,一般用于修改多个属性

    结算账户信息修改, status: 200(成功), return: 修改后的结算账户信息信息

    partial_update:
    结算账户信息--局部修改(一般修改一个属性),可以传参任意属性的值，服务器会修改指定的属性值

    结算账户信息局部修改, status: 200(成功), return: 修改后的结算账户信息信息

    list:
    结算账户信息--获取分页列表，可选json参数:name(名称)，remark(描述关键字),number_code(编号)

    {
        "name":"长沙",
        "remark":"xxx", "number_code":"xxxx"
    }
    结算账户信息列表信息, status: 200(成功), return: 结算账户信息信息列表

    retrieve:
    查询某一个结算账户信息

    查询指定ID的结算账户信息, status: 200(成功), return: 用户结算账户信息
    """

    queryset = SettlementAccountModel.objects.all()
    serializer_class = AccountSerializer
    pagination_class = GlobalPagination

    def get_queryset(self):
        if self.action == 'find':  # 如果视图函数是find的话
            # 获取参数
            name = self.request.data.get('name', None)
            remark = self.request.data.get('remark', None)
            number_code = self.request.data.get('number_code', None)

            query = Q()
            if name:
                # 字段 + contains 表示模糊查询
                query.add(Q(name__contains=name), 'AND')
            if remark:
                query.add(Q(remark__contains=remark), 'AND')
            if number_code:
                query.add(Q(number_code__contains=number_code), 'AND')

            return SettlementAccountModel.objects.filter(query).all()
        else:
            return SettlementAccountModel.objects.all()

    json__params = openapi.Schema(type=openapi.TYPE_OBJECT, properties={
        # 参数名：接一个类型（类型一个是openapi.Schema开头的）
        # 因为他是整数，所以要openapi.TYPE_INTEGER整数类型
        'name': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_STRING),
                               description='结算账户名称的关键字'),
        'remark': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_STRING),
                                 description='结算账户的描述的关键字'),
        'number_code': openapi.Schema(type=openapi.TYPE_ARRAY, items=openapi.Schema(type=openapi.TYPE_STRING),
                                 description='结算账户的编号的关键字'),
    })

    ''' 分页的页号和每页显示的数量只能通过get请求去传参的，这是drf框架规定的，但是swagger有一个属性manual_parameters是可以支持路径传参的 '''
    # 定义分页和页号
    # openapi.Parameter 请求路径的传参 openapi.IN_QUERY请求路径中传参
    page_param = openapi.Parameter(name='page', in_=openapi.IN_QUERY, description='页号', type=openapi.TYPE_INTEGER)
    # 因为在全局变量中已经规定好了叫size了，所以参数不能变
    size_param = openapi.Parameter(name='size', in_=openapi.IN_QUERY, description='每页显示的数量', type=openapi.TYPE_INTEGER)

    ''' 在drf框架中是get请求可以通过JSON格式传参的，只是swagger文档他生成注释的时候他不支持而已，
    之前的list视图函数（get请求）的时候就是用JSON格式传参的（例：/user/?id=3） '''


    # 这个是特别的接口文档，methods表示请求的方法，request_body表示指定传参
    # 注意点位：在swagger文档中如果用get请求他是不给你使用request_body，只有在post，delete，put，patch请求中才可以使用request_body
    # request_body就是JSON格式的传参
    @swagger_auto_schema(method='post', manual_parameters=[page_param, size_param], request_body=json__params,
                         operation_description='结算账户的过滤查询')  # 装饰器一定要写在action的上面
    @action(methods=['post'], detail=False)
    def find(self, request, *args, **kwargs):
        # 用于调用父类（超类）的方法。它提供了一种方便的方式来调用父类的方法，而不需要显式地指定父类的名称。
        # list函数是父类里面的函数（他是drf框架本身的代码）
        return super(AccountView, self).list(request=request, *args, **kwargs)
